package com.geng.demo.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class TokenUtil {
    private static final Logger logger = LogManager.getLogger(TokenUtil.class);

    public static final String APPID = "99cd36225338";
    public static final String SECRIT = "a346f3a4-9f1e-4b1c-977d-818c75520fda";
    /**
     * OA公钥-正式环境
     */
    public static final String SERVER_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbfMUaqAGbrlJpf3j6W915Sw7sWIHu+E1Grz6UAtJbm9JcJLhcPQvT5o06RBHzAHLS/nGjiqvPXcXPkQ2UARqo3zhkSb22HhzBZOfi/cIqwsqK1xWI9nz/PbVmxT+FjCpZmeDATdme5s0v8UkFLssS9iQ9Mw3APUiIPxGUbwqOvVmZ2wjA5qnrp/KtQTO+im+FJjXUyovYjDFihn/lYRY8y0JTOdTkuFEQ5JSUpJUmf7TSlWT/6Cz1qbTfKdpdR0ifQ8FC+Y2qdescAsvEo3spcqZ5+J/aYClWsenQbmyZj8o2aTlrN3HlQSxi5wV2hI1HdwEPFnvcGwvJ0gH5OupQIDAQAB";

    /**
     * token 口令字符串
     * invalidateTime 失效时间 localDateTime 1个小时
     */
    private ConcurrentHashMap<String, Object> tokenMap = new ConcurrentHashMap<>();
    private String appId;
    private String pubKey;
    /**
     * 获取缓存的token，缓存时间1小时
     * @return
     * token 口令  appId    pubKey
     */
    public Map<String, String> gainCacheToken(String ip){
        if(ObjectUtil.isEmpty(tokenMap)){
            Map<String, String> returnMap = gainOaToken(ip);
            tokenMap.put("token", returnMap.get("token"));
            appId = returnMap.get("appId");
            pubKey = returnMap.get("pubKey");
            LocalDateTime invalidateTime = LocalDateTime.now().plusMinutes(59); //失效时间59分钟
            tokenMap.put("invalidateTime", invalidateTime);
            return returnMap;
        }
        LocalDateTime invalidateTime = (LocalDateTime)tokenMap.get("invalidateTime");
        if(ObjectUtil.isEmpty(invalidateTime)){
            Map<String, String> returnMap = gainOaToken(ip);
            tokenMap.put("token", returnMap.get("token"));
            appId = returnMap.get("appId");
            pubKey = returnMap.get("pubKey");
            LocalDateTime invalidate = LocalDateTime.now().plusMinutes(59);  //失效时间59分钟
            tokenMap.put("invalidateTime", invalidate);
            return returnMap;
        }
        if(invalidateTime.isBefore(LocalDateTime.now())){
            Map<String, String> returnMap = gainOaToken(ip);
            tokenMap.put("token", returnMap.get("token"));
            appId = returnMap.get("appId");
            pubKey = returnMap.get("pubKey");
            LocalDateTime invalidate = LocalDateTime.now().plusMinutes(59);  //失效时间59分钟
            tokenMap.put("invalidateTime", invalidate);
            return returnMap;
        }
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("token", (String)tokenMap.get("token"));
        returnMap.put("appId", appId);
        returnMap.put("pubKey", pubKey);
        return returnMap;
    }

    /**
     * 获取OA的token，获取失败返回空字符串
     * @return token-口令 pubKey-公钥  appId-appId secrit-secrit
     */
    public Map<String, String> gainOaToken(String ip){
        //查询ECOLOGY_BIZ_EC表获取appid、secret、pubkey
        String appId = APPID;
        String secrit = SECRIT;
        String server_public_key = SERVER_PUBLIC_KEY;  //公钥
        //获取token授权
        String secret = encryptCode(server_public_key, secrit);
        String tokenUrl = ip + ":83/api/ec/dev/auth/applytoken";
        String tokenJson = sendPostGetToken(tokenUrl, appId, secret, "3600");
        JSONObject jsonObject = new JSONObject(tokenJson);
        String code = jsonObject.getStr("code");
        String tokenStr = jsonObject.getStr("token"); //OA的token
        if(!ObjectUtil.equal(code, "0")){
            logger.info("=configureTasksAtEight=获取token失败，定时任务跳过");
            return null;
        }
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("token", tokenStr);
        resultMap.put("pubKey", server_public_key);
        resultMap.put("appId", appId);
        resultMap.put("secrit", secrit);
        return resultMap;
    }

    /**
     * RSA加密
     * @param pubKey 公钥
     * @param secret 待加密字段
     * @return
     */
    public static String encryptCode(String pubKey, String secret){
        try {
            byte[] pubKeyBytes = Base64.getDecoder().decode(pubKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(keySpec);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] encryptedBytes = cipher.doFinal(secret.getBytes());
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 发送获取OAtoken的服务
     * @param url
     * @param appId
     * @param secret
     * @return
     */
    public static String sendPostGetToken(String url, String appId, String secret, String validateSecond){
        // 发起HTTP POST请求
        HttpResponse response = HttpRequest.post(url)
                .header("Content-Type", "application/json")
                .header("appid", appId)
                .header("secret", secret)
                .header("time", validateSecond)
                .execute();

        // 获取响应结果
        String result = response.body();
        return result;
    }

}
